package com.ocl.www.security;

import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import org.apache.log4j.Logger;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.mgt.FilterChainManager;
import org.apache.shiro.web.filter.mgt.FilterChainResolver;
import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
import org.apache.shiro.web.mgt.WebSecurityManager;
import org.apache.shiro.web.servlet.AbstractShiroFilter;
import org.springframework.beans.factory.BeanInitializationException;

/**
 * 
 * @ClassName: MShiroFilterFactoryBean
 * @Description: 继承 ShiroFilterFactoryBean 处理拦截资源文件问题
 * @author: xlh
 * @date: 2016年7月26日
 */
public class MShiroFilterFactoryBean extends ShiroFilterFactoryBean {
	private Logger log = Logger.getLogger(ShiroCasConfiguration.class);
	// 对ShiroFilter来说，需要直接忽略的请求
	private Set<String> ignoreExt;

	public MShiroFilterFactoryBean() {
		super();
		ignoreExt = new HashSet<String>();
		ignoreExt.add(".jpg");
		ignoreExt.add(".png");
		ignoreExt.add(".gif");
		ignoreExt.add(".bmp");
		ignoreExt.add(".js");
		ignoreExt.add(".css");
	}

	@Override
	protected AbstractShiroFilter createInstance() throws Exception {
		SecurityManager securityManager = getSecurityManager();
		if (securityManager == null) {
			throw new BeanInitializationException("SecurityManager property must be set");
		}

		if (!(securityManager instanceof WebSecurityManager)) {
			throw new BeanInitializationException(
					"The security manager does not implement the WebSecurityManager interface");
		}

		FilterChainManager filterChainManager = createFilterChainManager();
		PathMatchingFilterChainResolver chainResolver = new PathMatchingFilterChainResolver();
		chainResolver.setFilterChainManager(filterChainManager);

		return new MSpringShiroFilter((WebSecurityManager) securityManager, chainResolver);
	}

	private final class MSpringShiroFilter extends AbstractShiroFilter {

		protected MSpringShiroFilter(WebSecurityManager webSecurityManager, FilterChainResolver resolver) {
			super();
			if (webSecurityManager == null) {
				throw new IllegalArgumentException("WebSecurityManager property cannot be null");
			}

			setSecurityManager(webSecurityManager);
			if (resolver != null) {
				setFilterChainResolver(resolver);
			}
		}

		@Override
		protected void doFilterInternal(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws ServletException, IOException {
			HttpServletRequest request = (HttpServletRequest) servletRequest;

			String str = request.getRequestURI().toLowerCase();

			boolean flag = true;
			int idx = 0;
			if ((idx = str.indexOf(".")) > 0) {
				str = str.substring(idx);
				if (ignoreExt.contains(str.toLowerCase())) {
					flag = false;
				}
			}
			if (flag) {
				super.doFilterInternal(servletRequest, servletResponse, chain);
			} else {
				chain.doFilter(servletRequest, servletResponse);
			}
		}
	}

}
